﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Onixs.CmeFastHandler;
using System.Configuration;
using System.Threading;

namespace TAS
{
    public class TASEngine
    {
        public Dictionary<string, SecurityEntity> securityEntityMap = new Dictionary<string, SecurityEntity>();
        //protected static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public Handler fastMarketHandler;

        public double dummy;
        public DateTime starting, ending;

        public string fl = "CLX2", sl = "CLZ2", spr = "CLX2-CLZ2"; // this needs to be changed every month
        public string flID, slID, sprID;

        public SecurityEntity firstLeg = null;
        public SecurityEntity secondLeg = null;
        public SecurityEntity spread = null;

        private string channelConfigurationFile = "config.xml";
        private bool cacheSecurityDefinitions = false, replayLogFile = true;

        private int numberofSecurityDefinitions = 0;
        private double numberOfMessagesReceived = 0;

        private long lastMessageTimestamp;
        private long currentMessageTimestamp;
        private DateTime dLastMessageTimestamp, dCurrentMessageTimestamp;
        TimeSpan delay;
        private bool firstTrade = true;

        public DateTime simulationStartTime { get; set; }
        public DateTime simulationEndTime { get; set; }
        public bool simulation { get; set; }

        public bool booksReadyToTrade = false;

        TradeDataEntity handlerTradeDataEntity = new TradeDataEntity();

        public delegate void OrderTradeRecievedHandler(TradeDataEntity tradeDataEntity);
        public event OrderTradeRecievedHandler OnTradeRecievedHandler;

        public delegate void HandlerStateChanged(string message);
        public event HandlerStateChanged OnHandlerStateChanged;

        public void Initialize()
        {
            fastMarketHandler = new Handler("30");

            Handler.LogTrace("Sample Application 2.0.0.0");

            fastMarketHandler.ChannelConfigurationFile = channelConfigurationFile;
            fastMarketHandler.UseInstrumentReplayFeedA = true;
            fastMarketHandler.UseInstrumentReplayFeedB = false;

            fastMarketHandler.UseSnapshotFeedA = true;
            fastMarketHandler.UseSnapshotFeedB = false;

            fastMarketHandler.BestBidAskTrackingOptions.BestBidAskTrackingParameters = BestBidAskTrackingParameter.All;

            Handler.MaximumNumberOfQueuedIncrementalRefreshMessages = 100000;
            // add security description filters here

            fastMarketHandler.AddSecurityDescriptionFilter(fl);
            fastMarketHandler.AddSecurityDescriptionFilter(sl);
            fastMarketHandler.AddSecurityDescriptionFilter(spr);

            if (ConfigurationManager.AppSettings["DisposeFixMessages"] != null)
            {
                if (ConfigurationManager.AppSettings["DisposeFixMessages"].ToLowerInvariant() == "true")
                    fastMarketHandler.DisposeFixMessages = true;
                else
                    if (ConfigurationManager.AppSettings["DisposeFixMessages"].ToLowerInvariant() == "false")
                        fastMarketHandler.DisposeFixMessages = false;
            }

            if (ConfigurationManager.AppSettings["RecoverSecurityDefinitionsOnGap"] != null)
            {
                if (ConfigurationManager.AppSettings["RecoverSecurityDefinitionsOnGap"].ToLowerInvariant() == "true")
                    fastMarketHandler.RecoverSecurityDefinitionsOnGap = true;
                else
                    if (ConfigurationManager.AppSettings["RecoverSecurityDefinitionsOnGap"].ToLowerInvariant() == "false")
                        fastMarketHandler.RecoverSecurityDefinitionsOnGap = false;
            }

            if (ConfigurationManager.AppSettings["SubchannelsFilter"] != null)
            {
                string[] strValues = ConfigurationManager.AppSettings["SubchannelsFilter"].Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < strValues.Length; i++)
                    fastMarketHandler.AddSubchannelFilter(int.Parse(strValues[i]));
            }

            if (ConfigurationManager.AppSettings["SecurityIdsFilter"] != null)
            {
                string[] strValues = ConfigurationManager.AppSettings["SecurityIdsFilter"].Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < strValues.Length; i++)
                    fastMarketHandler.AddSecurityIdFilter(strValues[i]);
            }

            if (ConfigurationManager.AppSettings["SecurityDescriptionsFilter"] != null)
            {
                string[] strValues = ConfigurationManager.AppSettings["SecurityDescriptionsFilter"].Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < strValues.Length; i++)
                    fastMarketHandler.AddSecurityDescriptionFilter(strValues[i]);
            }

            if (ConfigurationManager.AppSettings["CacheSecurityDefinitions"] != null)
            {
                bool.TryParse(ConfigurationManager.AppSettings["CacheSecurityDefinitions"], out cacheSecurityDefinitions);
            }

            fastMarketHandler.ReplayFinished += new EventHandler<EventArgs>(MarketHandlerReplayFinished);
            fastMarketHandler.ReplayError += new EventHandler<Handler.ReplayErrorEventArgs>(MarketHandlerReplayError);
            fastMarketHandler.SecurityDefinitionReceived += new EventHandler<Handler.SecurityDefinitionReceivedEventArgs>(MarketHandlerSecurityDefinitionReceived);
            fastMarketHandler.RegularOrderBookUpdated += new EventHandler<Handler.OrderBookUpdatedEventArgs>(MarketHandlerRegularOrderBookUpdated);
            fastMarketHandler.ImpliedOrderBookUpdated += new EventHandler<Handler.OrderBookUpdatedEventArgs>(MarketHandlerImpliedOrderBookUpdated);
            fastMarketHandler.ConsolidatedOrderBookUpdated += new EventHandler<Handler.OrderBookUpdatedEventArgs>(MarketHandlerConsolidatedOrderBookUpdated);
            fastMarketHandler.ImpliedOrderBookTopOfTheBookUpdated += new EventHandler<Handler.TopOfTheOrderBookUpdatedEventArgs>(MarketHandlerImpliedOrderBookTopOfTheBookUpdated);
            fastMarketHandler.RegularOrderBookTopOfTheBookUpdated += new EventHandler<Handler.TopOfTheOrderBookUpdatedEventArgs>(MarketHandlerRegularOrderBookTopOfTheBookUpdated);
            fastMarketHandler.ConsolidatedOrderBookTopOfTheBookUpdated += new EventHandler<Handler.TopOfTheOrderBookUpdatedEventArgs>(MarketHandlerConsolidatedOrderBookTopOfTheBookUpdated);

            fastMarketHandler.NewsReceived += new EventHandler<Handler.NewsReceivedEventArgs>(MarketHandlerNewsReceived);

            fastMarketHandler.Error += new EventHandler<Handler.ErrorEventArgs>(MarketHandlerError);
            fastMarketHandler.Warning += new EventHandler<Handler.WarningEventArgs>(MarketHandlerWarning);
            fastMarketHandler.Info += new EventHandler<Handler.InfoEventArgs>(MarketHandlerInfo);
            fastMarketHandler.NoDataOnFeedReceived += new EventHandler<Handler.NoDataOnFeedReceivedEventArgs>(MarketHandlerNoDataOnFeedReceived);
            fastMarketHandler.StateChanged += new EventHandler<Handler.StateChangedEventArgs>(MarketHandlerStateChanged);
            fastMarketHandler.SecurityStatusChanged += new EventHandler<Handler.SecurityStatusChangedEventArgs>(MarketHandlerSecurityStatusChanged);
            // added by MS
            fastMarketHandler.MessageProcessingStarted += new EventHandler<Handler.MessageProcessingStartedEventArgs>(MessageProcessingStarted);
            //
            fastMarketHandler.MessageProcessingFinished += new EventHandler<Handler.MessageProcessingFinishedEventArgs>(MarketHandlerMessageProcessingFinished);
            fastMarketHandler.Trade += new EventHandler<Handler.TradeEventArgs>(MarketHandlerTrade);
            fastMarketHandler.Statistics += new EventHandler<Handler.StatisticsEventArgs>(MarketHandlerStatistics);
            
			if (replayLogFile == true )
			{
               // ReplayLogFile("Sample//log.txt");
                ReplayLogFile("CmeMarketDataHandler-Channel_30.log");
			}
			else
			{
				Connect();
			}
        }

    	private void Connect()
		{
            fastMarketHandler.Start(BooksMaintenanceOptions.All, cacheSecurityDefinitions);

            // request for security definitions in a while true loop.

            while (true)
            {
                Thread.Sleep(0);

                if (fastMarketHandler.State == HandlerState.SecurityDefinitionsRecoveryFinished)
                {
                    break;
                }
            }
		}

    	private void ReplayLogFile(string fileName)
		{
            try
            {
                //log.Info("Starting replay from log file");
                fastMarketHandler.Start(BooksMaintenanceOptions.All, new ReplayOptions(fileName) { DelayBetweenMessages = 1 });
            }
            catch (Exception ex)
            {
                //log.Error(ex.Message);
            }
		}

        void MarketHandlerReplayError(object sender, Handler.ReplayErrorEventArgs e)
        {
            //log.Info("Replay log file error: " + e.Description);
        }

        void MarketHandlerReplayFinished(object sender, EventArgs e)
        {
            Console.WriteLine("Replay Finished");
            //log.Info("Replay log file finished");
        }

        void MarketHandlerRegularOrderBookUpdated(object sender, Handler.OrderBookUpdatedEventArgs e)
        {
            Handler.LogTrace("MarketHandlerregularorderbookupdated");
            //log.Info("Market Handler : Regular Order Book updated : " + e.SendingTime.ToString());

            if (e.Book.SecurityId.Equals(this.flID))
                firstLeg.regularOrderBook = e.Book;
            else if (e.Book.SecurityId.Equals(this.slID))
                secondLeg.regularOrderBook = e.Book;
            else if (e.Book.SecurityId.Equals(this.sprID))
                spread.regularOrderBook = e.Book;            
        }

        void MarketHandlerImpliedOrderBookUpdated(object sender, Handler.OrderBookUpdatedEventArgs e)
        {
            Handler.LogTrace("MarketHandlerimpliedorderbookupdated");
            //log.Info("Market Handler : Implied Order Book updated : " + e.SendingTime.ToString());

            if (e.Book.SecurityId.Equals(this.flID))
                firstLeg.impliedOrderBook= e.Book;
            else if (e.Book.SecurityId.Equals(this.slID))
                secondLeg.impliedOrderBook = e.Book;
            else if (e.Book.SecurityId.Equals(this.sprID))
                spread.impliedOrderBook = e.Book;
        }

        void MarketHandlerConsolidatedOrderBookUpdated(object sender, Handler.OrderBookUpdatedEventArgs e)
        {
            Handler.LogTrace("MarketHandlerconsolidatedorderbookupdated");
            //log.Info("Market Handler : Consolidated Order Book updated : " + e.SendingTime.ToString());

            if (e.Book.SecurityId.Equals(this.flID))
                firstLeg.consolidatedOrderBook= e.Book;
            else if (e.Book.SecurityId.Equals(this.slID))
                secondLeg.consolidatedOrderBook = e.Book;
            else if (e.Book.SecurityId.Equals(this.sprID))
                spread.consolidatedOrderBook = e.Book;
        }

        void MarketHandlerSecurityDefinitionReceived(object sender, Handler.SecurityDefinitionReceivedEventArgs e)
        {
            //Handler.LogTrace("MarketHandlersecuritydefinitionsrecieved");
            ////log.Info("Market Handler : Security Definitions recieved : " + numberofSecurityDefinitions++);

            if (e.SecurityDescription == this.fl)
            {
                firstLeg = new SecurityEntity();
                firstLeg.Initialize(e.SecurityDescription, e.SecurityId);
                securityEntityMap.Add(this.fl, firstLeg);
                this.flID = e.SecurityId;
            }
            else if (e.SecurityDescription == this.sl)
            {
                secondLeg = new SecurityEntity();
                secondLeg.Initialize(e.SecurityDescription, e.SecurityId);
                securityEntityMap.Add(this.sl, secondLeg);
                this.slID = e.SecurityId;
            }
            else if (e.SecurityDescription == this.spr)
            {
                spread = new SecurityEntity();
                spread.Initialize(e.SecurityDescription, e.SecurityId);
                securityEntityMap.Add(this.spr, spread);
                this.sprID = e.SecurityId;
            }            
        }

        void MarketHandlerTrade(object sender, Handler.TradeEventArgs e)
        {
            ////log.Info("Market Handler : Trade Recieved : " + e.SendingTime.ToString());
            ////log.Info(e.ToString());

            handlerTradeDataEntity.Price = (long)e.Price;
            handlerTradeDataEntity.Quantity = e.Size;
            handlerTradeDataEntity.Time = e.SendingTime;
            handlerTradeDataEntity.SecurityID = e.SecurityId;
            handlerTradeDataEntity.AggressorSide = e.AggressorSide;

            handlerTradeDataEntity.isTrade = true;
           

            // TESTING PURPOSES - Replaying log files

            if (OnTradeRecievedHandler != null)
            {
                OnTradeRecievedHandler(handlerTradeDataEntity);
            }

            if (e.SecurityId == this.flID)
                firstLeg.UpdateData(handlerTradeDataEntity);
            else if (e.SecurityId == this.slID)
                secondLeg.UpdateData(handlerTradeDataEntity);
            else if (e.SecurityId == this.sprID)
                spread.UpdateData(handlerTradeDataEntity);
            else
                Console.WriteLine("Trade Data out of the filters" + e.SecurityId);
        }

        void MarketHandlerStatistics(object sender, Handler.StatisticsEventArgs e)
        {
            Handler.LogTrace("MarketHandlerstatistics");
            //log.Info("Market Handler : Statistics : " + e.ToString());
        }

        // added by MS
        void MessageProcessingStarted(object sender, Handler.MessageProcessingStartedEventArgs e)
        {
            numberOfMessagesReceived++;

            //Thread.CurrentThread.Priority = ThreadPriority.Highest;
            //log.Info("Message Received: " + e.Message + DateTime.Now);
            
           // System.Diagnostics.Trace.WriteLine(numberOfMessagesReceived + "  " + e.Message);
    
            //currentMessageTimestamp = ParseMessage(e.Message.ToString());
            
            /*dCurrentMessageTimestamp = DParseMessage(e.Message.ToString());

            if (simulation == true)
            {
                if (dCurrentMessageTimestamp > simulationStartTime && dCurrentMessageTimestamp <= simulationEndTime)
                {
                    if (firstTrade == true)
                    {
                        dLastMessageTimestamp = dCurrentMessageTimestamp;
                        firstTrade = false;
                    }

                    delay = dCurrentMessageTimestamp.Subtract(dLastMessageTimestamp);

                    if (delay.Milliseconds > 1)
                    {
                        Thread.Sleep((int)delay.TotalMilliseconds);
                    }
                }
            }
            else if (numberOfMessagesReceived > 1)
            {
                int delay = (int)(currentMessageTimestamp - lastMessageTimestamp);
                if (delay > 1)
                {
                   // Thread.Sleep(delay);
                }
            }

            dLastMessageTimestamp = dCurrentMessageTimestamp;*/
        }

        void MarketHandlerMessageProcessingFinished(object sender, Handler.MessageProcessingFinishedEventArgs e)
        {
            Handler.LogTrace("MarketHandlermessageprocessingfinished");
        }

        void MarketHandlerStateChanged(object sender, Handler.StateChangedEventArgs e)
        {
            
            Console.WriteLine("Market Handler : State Changed from " + e.OldState.ToString() + " to " + e.NewState.ToString() + DateTime.Now);

            OnHandlerStateChanged("Market Handler : State Changed from " + e.OldState.ToString() + " to " + e.NewState.ToString() + DateTime.Now);

            if (e.NewState.ToString() == "BooksResynchronizationFinished")
            {
                booksReadyToTrade = true;
            }
            else
            {
                booksReadyToTrade = false;
            }
            if (e.NewState.ToString() == "Stopped")
            {
                Console.WriteLine("Market Handler : State Changed from " + e.OldState.ToString() + " to " + e.NewState.ToString() + DateTime.Now);

            }
        }

        void UpdateHandlerState(string state)
        {
            //log.Info("Market Handler : Update Handler state");
        }

        void MarketHandlerNoDataOnFeedReceived(object sender, Handler.NoDataOnFeedReceivedEventArgs e)
        {
            //log.Info("Market Handler : No Data on Feed");
        }

        void MarketHandlerInfo(object sender, Handler.InfoEventArgs e)
        {
            //log.Info("Market Handler : Information : " + e.Reason);
        }

        void MarketHandlerWarning(object sender, Handler.WarningEventArgs e)
        {
            //log.Info("Market Handler : Warning" + " " + e.Description + " " + e.Reason);
        }

        void MarketHandlerError(object sender, Handler.ErrorEventArgs e)
        {
            //log.Info("Market Handler : Error" + e.Description + " " + e.Reason);
        }

        void MarketHandlerSecurityStatusChanged(object sender, Handler.SecurityStatusChangedEventArgs e)
        {
            Console.WriteLine("Market Handler : Security Status Changed");
            if (e.SecurityStatus == SecurityStatus.ReadyToTrade)
            {
                if (e.SecurityId == this.flID)
                    firstLeg.securityStatus = e.SecurityStatus;
                else if (e.SecurityId == this.slID)
                    secondLeg.securityStatus = e.SecurityStatus;
                else if (e.SecurityId == this.sprID)
                    spread.securityStatus = e.SecurityStatus;
            }
        }

        void MarketHandlerNewsReceived(object sender, Handler.NewsReceivedEventArgs e)
        {
            //log.Info("Market Handler : News Recieved");
        }

        void MarketHandlerRegularOrderBookTopOfTheBookUpdated(object sender, Handler.TopOfTheOrderBookUpdatedEventArgs e)
        {
            handlerTradeDataEntity.bestAsk = e.BestAsk;
            handlerTradeDataEntity.bestBid = e.BestBid;
            handlerTradeDataEntity.SecurityID = e.SecurityId;
            handlerTradeDataEntity.isTrade = false;

            OnTradeRecievedHandler(handlerTradeDataEntity);

            
            //log.Info("Market Handler : Regular OrderBook Top of the Book updated");
            if (e.SecurityId.Equals(this.flID))
            {
                firstLeg.bestAsk = e.BestAsk;
                firstLeg.bestBid = e.BestBid;
            }
            else if (e.SecurityId.Equals(this.slID))
            {
                secondLeg.bestAsk = e.BestAsk;
                secondLeg.bestBid = e.BestBid;
            }
            else if (e.SecurityId.Equals(this.sprID))
            {
                spread.bestAsk = e.BestAsk;
                spread.bestBid = e.BestBid;
            }

            

            if (booksReadyToTrade)
            {
                
                if ((firstLeg.lastTradedPrice - secondLeg.bestBid.Price - spread.bestBid.Price) < -2)
                {
                    dummy = firstLeg.lastTradedPrice - secondLeg.bestBid.Price - spread.bestBid.Price;
                    System.Diagnostics.Trace.WriteLine("Spread Arbitrage: BO: " + " " + firstLeg.lastTradedPrice + " " + secondLeg.bestBid.Price + " " + spread.bestBid.Price + " " + dummy);
                }
                else if ((secondLeg.bestAsk.Price - firstLeg.lastTradedPrice + spread.bestAsk.Price)< -2)
                {
                    dummy = secondLeg.bestAsk.Price - firstLeg.lastTradedPrice + spread.bestAsk.Price;
                    System.Diagnostics.Trace.WriteLine("Spread Arbitrage: SO: " + " " + firstLeg.lastTradedPrice + " " + secondLeg.bestAsk.Price + " " + spread.bestAsk.Price + " " + dummy);
                }
            }
            
        }

        void MarketHandlerImpliedOrderBookTopOfTheBookUpdated(object sender, Handler.TopOfTheOrderBookUpdatedEventArgs e)
        {
            //log.Info("Market Handler : Implied OrderBook Top of the Book updated");
            if (e.SecurityId.Equals(this.flID))
            {
                firstLeg.bestAskIOB = e.BestAsk;
                firstLeg.bestBidIOB = e.BestBid;
            }
            else if (e.SecurityId.Equals(this.slID))
            {
                secondLeg.bestAskIOB = e.BestAsk;
                secondLeg.bestBidIOB = e.BestBid;
            }
            else if (e.SecurityId.Equals(this.sprID))
            {
                spread.bestAskIOB = e.BestAsk;
                spread.bestBidIOB = e.BestBid;
            }
        }

        void MarketHandlerConsolidatedOrderBookTopOfTheBookUpdated(object sender, Handler.TopOfTheOrderBookUpdatedEventArgs e)
        {
            //log.Info("Market Handler : Consolidated OrderBook Top of the Book updated");
            if (e.SecurityId.Equals(this.flID))
            {
                firstLeg.bestAskCOB = e.BestAsk;
                firstLeg.bestBidCOB = e.BestBid;
            }
            else if (e.SecurityId.Equals(this.slID))
            {
                secondLeg.bestAskCOB = e.BestAsk;
                secondLeg.bestBidCOB = e.BestBid;
            }
            else if (e.SecurityId.Equals(this.sprID))
            {
                spread.bestAskCOB = e.BestAsk;
                spread.bestBidCOB = e.BestBid;
            }
        }

        //This is the Entry point of Trade data into TAS
        //This function checks for the securityID in the incoming fix message
        //TAS creates a 'SecurityTradeData' class object for each new SecurityID if this is the first time you recieve 
        //Trade Data for this securityID.
        //TAS stores the 'SecurityTradeData' object and the SecurityID as a 'Key-Value' pair in the 'securityTradeDataMap'
        //Dictionary.
       
        public void LogData()
        {
            foreach (var item in securityEntityMap)
            {
                item.Value.LogData();
            }
        }

        public long ParseMessage(string fixMessage)
        {
             string[] valuePairs = fixMessage.Split((char)1);

             foreach (string valuePair in valuePairs)
             {
                 string[] tagValue = valuePair.Split('=');

                 if (tagValue[0].Equals("52"))
                 {
                    return ConvertToLong(tagValue[1]);
                    break;
                 }
             }
             return 0;
        }

        public DateTime DParseMessage(string fixMessage)
        {
            string[] valuePairs = fixMessage.Split((char)1);
            DateTime dt = new DateTime(10,10,10,0,0,0,0);
            int y, m, d, h, mi, ss, ms;
            char[] str;
            string s;
            foreach (string valuePair in valuePairs)
            {
                string[] tagValue = valuePair.Split('=');

                if (tagValue[0].Equals("52"))
                {
                    str = tagValue[1].ToCharArray();
                    s = new string(str, 0, 4);
                    y = (int)ConvertToLong(s);
                    s = new string(str, 4, 2);
                    m = (int)ConvertToLong(s); 
                    s = new string(str, 6, 2);
                    d = (int)ConvertToLong(s); 
                    s = new string(str, 8, 2);
                    h = (int)ConvertToLong(s); 
                    s = new string(str, 10, 2);
                    mi = (int)ConvertToLong(s);
                    s = new string(str, 12, 2);
                    ss = (int)ConvertToLong(s); 
                    s = new string(str, 14, 3);
                    ms = (int)ConvertToLong(s);
                    dt = new DateTime(y, m, d, h, mi, ss, ms);
                    return dt;
                    break;
                }
            }
            return dt;
        }

        private long ConvertToLong(string str1)
        {
            char[] str = str1.ToCharArray();
            long i = str1.Length;
            long number = 0;
            for (int j = 0; j < i; j++)
            {
                if (str[j] == '0')
                    number = number * 10 + 0;
                else if (str[j] == '1')
                    number = number * 10 + 1;
                else if (str[j] == '2')
                    number = number * 10 + 2;
                else if (str[j] == '3')
                    number = number * 10 + 3;
                else if (str[j] == '4')
                    number = number * 10 + 4;
                else if (str[j] == '5')
                    number = number * 10 + 5;
                else if (str[j] == '6')
                    number = number * 10 + 6;
                else if (str[j] == '7')
                    number = number * 10 + 7;
                else if (str[j] == '8')
                    number = number * 10 + 8;
                else if (str[j] == '9')
                    number = number * 10 + 9;
            }
            
            return number;
        }

        public OHLCEntity ReadData(string securityID, int timespan)
        {
            // based on parameters passed, read SecurityEntity and return the correcsponding
            // values for the security

            SecurityEntity securityEntity = securityEntityMap[securityID];
            OHLCEntity lastOHLC = securityEntity.getOHLC(timespan);
            return lastOHLC;
            
        }

        public BollingerEntity ReadData(int timespan, string securityID)
        {
            // based on parameters passed, read SecurityEntity and return the correcsponding
            // values for the security

            SecurityEntity securityEntity = securityEntityMap[securityID];
            BollingerEntity lastBOLL = securityEntity.getBOLL(timespan);
            return lastBOLL;

        }


        public DateTime DSTime(string str1)
        {
            DateTime dt = new DateTime(10, 10, 10, 0, 0, 0, 0);
            int y, m, d, h, mi, ss, ms;
            char[] str;
            string s;
            str = str1.ToCharArray();
            s = new string(str, 0, 4);
            y = (int)ConvertToLong(s);
            s = new string(str, 4, 2);
            m = (int)ConvertToLong(s);
            s = new string(str, 6, 2);
            d = (int)ConvertToLong(s);
            s = new string(str, 8, 2);
            h = (int)ConvertToLong(s);
            s = new string(str, 10, 2);
            mi = (int)ConvertToLong(s);
            s = new string(str, 12, 2);
            ss = (int)ConvertToLong(s);
            s = new string(str, 14, 3);
            ms = (int)ConvertToLong(s);
            dt = new DateTime(y, m, d, h, mi, ss, ms);
            return dt;
            
        }
    }
}
